package net.hn.hnms.biz.blueprint.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import net.hn.hnms.biz.blueprint.domain.Catalog;
import net.hn.hnms.biz.blueprint.domain.FileInfo;
import net.hn.hnms.biz.blueprint.domain.FileInfoRecord;
import net.hn.hnms.biz.blueprint.domain.FileTypeInfo;
import net.hn.hnms.biz.blueprint.mapper.CatalogMapper;
import net.hn.hnms.biz.blueprint.mapper.FileInfoMapper;
import net.hn.hnms.biz.blueprint.mapper.FileInfoRecordMapper;
import net.hn.hnms.biz.blueprint.mapper.FileTypeInfoMapper;
import net.hn.hnms.biz.blueprint.request.FileInfoDeleteReq;
import net.hn.hnms.biz.blueprint.request.FileInfoReq;
import net.hn.hnms.biz.blueprint.request.FileSaveReq;
import net.hn.hnms.biz.blueprint.service.IFileInfoService;
import net.hn.hnms.biz.blueprint.vo.FileInfoPageVO;
import net.hn.hnms.sys.common.core.constant.Constants;
import net.hn.hnms.sys.common.core.domain.R;
import net.hn.hnms.sys.common.core.domain.ResponsePage;
import net.hn.hnms.sys.common.core.exception.HuaNengException;
import net.hn.hnms.sys.common.core.utils.tool.Func;
import net.hn.hnms.sys.common.mybatis.core.page.PageQuery;
import net.hn.hnms.sys.file.api.RemoteFileService;
import net.hn.hnms.sys.system.api.RemoteUserService;
import net.hn.hnms.sys.system.api.model.LoginUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author wangjr
 * 图纸文档管理服务层实现
 * @date 2022-09-13
 */

@Service
public class FileInfoServiceImpl extends BaseService<FileInfo, FileInfoPageVO> implements IFileInfoService {

    private final static Logger log = LoggerFactory.getLogger(FileInfoServiceImpl.class);

    @Autowired
    private FileInfoMapper fileInfoMapper;

    @Autowired
    private FileTypeInfoMapper fileTypeInfoMapper;

    @Autowired
    private FileInfoRecordMapper fileInfoRecordMapper;

    @Autowired
    private CatalogMapper catalogMapper;

    @Autowired
    private RemoteFileService fileService;
    @Autowired
    private RemoteUserService remoteUserService;
    /**
     * 文件列表
     */
    @Override
    public ResponsePage<FileInfoPageVO> selectPageList(FileInfoReq req, PageQuery pageQuery) {
        Catalog catalog = catalogMapper.selectById(req.getCatalogId());
        if(null == catalog) throw new HuaNengException(Constants.FAIL,"目录不存在");
        Long[] fileOssIds = catalog.getOssIds();
        if(null == fileOssIds || fileOssIds.length == 0) return null;

        LambdaQueryWrapper<FileInfo> query = Wrappers.lambdaQuery();
        String username = req.getUsername();
        if(StrUtil.isNotBlank(username)){
//            LoginUser userInfo = remoteUserService.getUserInfo(username);
//            if (null == userInfo.getUserId()) return null;
//            query.eq(FileInfo::getCreateUserId,userInfo.getUserId().toString());

            List<LoginUser> loginUsers = remoteUserService.getUserListByChUserName(req.getUsername());
            if (Optional.ofNullable(loginUsers).isPresent()) {
                List<Long> collect = loginUsers.stream().map(LoginUser::getUserId).collect(Collectors.toList());
                List<String> collect1 = collect.stream().map(String::valueOf).collect(Collectors.toList());
                query.in(Func.isNotEmpty(collect1),FileInfo::getCreateUserId,collect1);
            }else{
                return new ResponsePage(new ArrayList(), 0);
            }


        }
        query.like(StrUtil.isNotBlank(req.getFileName()),FileInfo::getFileName,req.getFileName());
        query.in(FileInfo::getOssId,Arrays.asList(fileOssIds));
        query.eq(StrUtil.isNotBlank(req.getFileTypeId()),FileInfo::getFileTypeId,req.getFileTypeId());
        query.eq(StrUtil.isNotBlank(req.getSuffixType()),FileInfo::getSuffixType,req.getSuffixType());
        query.eq(StrUtil.isNotBlank(req.getMineCode()),FileInfo::getMineCode,req.getMineCode());

        query.and(o->o.eq(StrUtil.isNotBlank(req.getMineCode()),FileInfo::getMineCode,req.getMineCode()).or().eq(StrUtil.isNotBlank(req.getCompanyCode()),FileInfo::getCompanyCode,req.getCompanyCode()));

        if(req.getBeginDate() != null) query.apply(" create_time >= to_timestamp('"+ DateUtil.formatDate(req.getBeginDate())+"','yyyy-mm-dd hh24:mi:ss') ");
        if(req.getEndDate() != null) query.apply(" create_time <= to_timestamp('"+DateUtil.formatDate(req.getEndDate())+"','yyyy-mm-dd hh24:mi:ss') ");

        IPage<FileInfo> pageResult = fileInfoMapper.selectVoPage(pageQuery.build(), query);
        List<FileInfoPageVO> result = new ArrayList<>(pageResult.getRecords().size());
        pageResult.getRecords().forEach(item -> {
            LoginUser user = remoteUserService.getUserInfoById(Long.valueOf(item.getCreateUserId()));
            FileTypeInfo fileType = fileTypeInfoMapper.selectById(item.getFileTypeId());
            FileInfoPageVO vo = BeanUtil.copyProperties(item, FileInfoPageVO.class);
//            vo.setUsername(user.getUsername());
            vo.setUsername(user.getNickname());
            vo.setFileTypeName(fileType.getFileTypeName());
            result.add(vo);
        });
        return new ResponsePage(result, pageResult.getTotal());
    }

    /**
     * 获取文件类型
     */
    private FileTypeInfo getFileType(String fileTypeName) {
        LambdaQueryWrapper<FileTypeInfo> query = Wrappers.lambdaQuery();
        query.eq(FileTypeInfo::getFileTypeName, fileTypeName);
        FileTypeInfo fileType = fileTypeInfoMapper.selectOne(query);
        if(null == fileType) {
            fileType = new FileTypeInfo();
            fileType.setFileTypeName(fileTypeName);
            fileTypeInfoMapper.insert(fileType);
        }
        return fileType;
    }

    /**
     * 上传或版本更新
     */
    @Transactional
    @Override
    public void save(FileSaveReq req) {
        try {
            FileInfo fileInfo = new FileInfo();
            if(StrUtil.isNotBlank(req.getFileInfoId())){
                fileInfo = getFileInfoById(req.getFileInfoId());
            }
            FileTypeInfo fileType = getFileType(req.getFileTypeName());

            fileInfo.setFileName(req.getFileName());
            fileInfo.setMineCode(req.getMineCode());
            fileInfo.setFileSize(req.getFileSize());
            fileInfo.setSuffixType(FileUtil.getSuffix(req.getFileName()));
            fileInfo.setFileTypeId(fileType.getFileTypeId());
            fileInfo.setVersionCode(req.getVersionCode());
            fileInfo.setFilePath(req.getFilePath());
            fileInfo.setOssId(req.getOssId());

            Catalog catalog = catalogMapper.selectById(req.getCatalogId());
            Set<Long> ossIdList = new HashSet<>();
            if(null != catalog.getOssIds()) {
                ossIdList = Stream.of(catalog.getOssIds()).collect(Collectors.toSet());
            }
            ossIdList.add(req.getOssId());
            catalog.setOssIds(ossIdList.toArray(new Long[ossIdList.size()]));

            catalogMapper.updateById(catalog);
            fileInfoMapper.insertOrUpdate(fileInfo);
            fileInfoRecordMapper.insert(BeanUtil.copyProperties(fileInfo, FileInfoRecord.class));
        } catch (Exception e) {
            fileService.remove(new Long[]{req.getOssId()});
            throw e;
        }
    }

    /**
     * 根据id获取文件信息
     */
    private FileInfo getFileInfoById(String fileInfoId){
        FileInfo fileInfo = fileInfoMapper.selectById(fileInfoId);
        if(null == fileInfo) throw new HuaNengException(Constants.FAIL,"文件不存在");
        return fileInfo;
    }

    /**
     * 文件删除
     */
    @Transactional
    @Override
    public void delete(FileInfoDeleteReq req) {
        List<FileInfo> fileInfos = fileInfoMapper.selectBatchIds(req.getFileInfoIds());
        if(CollUtil.isEmpty(fileInfos)) throw new HuaNengException(Constants.FAIL,"文件不存在或已被删除");
        Long[] ossIds = fileInfos.stream().map(FileInfo::getOssId).toArray(Long[]::new);

        Catalog catalog = catalogMapper.selectById(req.getCatalogId());
        if(null == catalog) throw new HuaNengException(Constants.FAIL,"目录不存在");

        fileInfoMapper.deleteBatchIds(req.getFileInfoIds());

        List<String> fileInfoIdList = fileInfos.stream().map(FileInfo::getFileInfoId).collect(Collectors.toList());
        QueryWrapper<FileInfoRecord> deleteWrapper = new QueryWrapper<>();
        deleteWrapper.in("file_info_id",fileInfoIdList);
        fileInfoRecordMapper.delete(deleteWrapper);

        if(catalog.getOssIds() != null && catalog.getOssIds().length != 0) {
            List<Long> ossIdsList = new ArrayList<>(Arrays.asList(catalog.getOssIds()));
            CollUtil.removeAny(ossIdsList, ossIds);
            catalog.setOssIds(ossIdsList.toArray(new Long[ossIdsList.size()]));
            catalogMapper.updateById(catalog);
        }
        R<Void> result = fileService.remove(ossIds);
        if(result.getCode() != 200){
            throw new HuaNengException(Constants.FAIL,result.getMsg());
        }
    }

    /**
    * 页面下拉框字典
    *  */
    @Override
    public List<Map<String, Object>> dictList(String mineCode,String companyCode) {
        List<Map<String, Object>> result = new ArrayList<>();
        LambdaQueryWrapper<FileInfo> queryFileInfo = new LambdaQueryWrapper<>();
        queryFileInfo.eq(StrUtil.isNotBlank(mineCode),FileInfo::getMineCode,mineCode);
        queryFileInfo.and(o->o.eq(StrUtil.isNotBlank(mineCode),FileInfo::getMineCode,mineCode).or().eq(StrUtil.isNotBlank(companyCode),FileInfo::getCompanyCode,companyCode));

        queryFileInfo.groupBy(FileInfo::getSuffixType);

        queryFileInfo.select(FileInfo::getSuffixType);
        List<Map<String, Object>> allSuffix = fileInfoMapper.selectMaps(queryFileInfo);
        if(CollUtil.isNotEmpty(allSuffix)) result.addAll(allSuffix);

        LambdaQueryWrapper<FileTypeInfo> queryType = new LambdaQueryWrapper<>();
        queryType.eq(StrUtil.isNotBlank(mineCode),FileTypeInfo::getMineCode,mineCode);
        queryType.and(o->o.eq(StrUtil.isNotBlank(mineCode),FileTypeInfo::getMineCode,mineCode).or().eq(StrUtil.isNotBlank(companyCode),FileTypeInfo::getCompanyCode,companyCode));

        queryType.groupBy(FileTypeInfo::getFileTypeName);

        queryType.select(FileTypeInfo::getFileTypeName);
        List<Map<String, Object>> allType = fileTypeInfoMapper.selectMaps(queryType);
        if(CollUtil.isNotEmpty(allType)) result.addAll(allType);
        return result;
    }

    @Override
    public List<FileTypeInfo> dictFileTypelist(String mineCode, String companyCode) {
        LambdaQueryWrapper<FileTypeInfo> queryFileInfo = new LambdaQueryWrapper<>();
        queryFileInfo.eq(StrUtil.isNotBlank(mineCode),FileTypeInfo::getMineCode,mineCode);
        queryFileInfo.and(o->o.eq(StrUtil.isNotBlank(mineCode),FileTypeInfo::getMineCode,mineCode).or().eq(StrUtil.isNotBlank(companyCode),FileTypeInfo::getCompanyCode,companyCode));
        List<FileTypeInfo> fileInfos = fileTypeInfoMapper.selectList(queryFileInfo);

        return fileInfos;
    }
}
